package com.gopay.bis.icbc.ebank.operation;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;

import cn.com.infosec.icbc.ReturnValue;
import cn.com.infosec.util.Base64;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.TransUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.icbc.ebank.pay.IcbcB2cMessage;
import com.gopay.common.domain.bank.icbc.ebank.pay.res.PayB2CRes;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.ICertHelperIcbcB2c;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 工行B2C签名验签实现
 * 
 * @IcbcB2bCertHelper.java
 * @author WangHongFei
 */
public class IcbcB2cCertHelper implements ICertHelperIcbcB2c {

	public String sign(BaseMessage message) throws GopayException{
		try {
			
			IcbcB2cMessage messageb2c = (IcbcB2cMessage) message;
			BankLogUtils.printB2CSignPlainLog(messageb2c);
			byte[] transDataByte = messageb2c.getPlainMessage().getBytes("UTF-8");
			byte[] fileSkByte = null;
			char[] keyStorePwdChar = null;
			fileSkByte = TransUtils.getFile(messageb2c.getPrivateKeyPath());
			keyStorePwdChar = messageb2c.getPrivatePwd().toCharArray();
			byte[] transDataSignature = null;
			transDataSignature = ReturnValue.sign(transDataByte,transDataByte.length, fileSkByte, keyStorePwdChar);
			byte[] encTransDataSignature = ReturnValue.base64enc(transDataSignature);
			String signatureWithBase64 = new String(encTransDataSignature);
			BankLogUtils.printB2BSignSignatureLog(messageb2c,System.getProperty("file.encoding"));
			BankLogUtils.printB2CSignSignatureLog(messageb2c, signatureWithBase64);
			return signatureWithBase64;
		} catch (Exception e) {
			BankLogUtils.printB2CSignExceptionLog(message, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
		}
	}

	public Object verify(BaseMessage message) throws GopayException{
		try {
			IcbcB2cMessage b2cMessage = (IcbcB2cMessage) message;
			String plainMessage =new String(Base64.decode(new String(message.getPlainMessage().getBytes("GBK"), "UTF-8")), "GBK");
			BufferedWriter out = new BufferedWriter(new FileWriter("/usr/local/ciecc/webapps/logs/bis/icbc/test.txt"));
		    out.write(plainMessage);
		    out.close();
			b2cMessage.setPlainMessage(plainMessage);
			byte[] plainSrc = plainMessage.getBytes("GBK");
			byte[] verifyPkByte = null;			
			byte[] signSrc = Base64.decode(new String( b2cMessage.getSignMessage().getBytes("GBK"), "UTF-8"));
			verifyPkByte = TransUtils.getFile(b2cMessage.getPrivateKeyPath2nd());
			int verifyRes = ReturnValue.verifySign(plainSrc,plainSrc.length, verifyPkByte, signSrc);
			BankLogUtils.printB2CVerifyPlainLog(b2cMessage);
			BankLogUtils.printB2CVerifySignatureLog(b2cMessage, b2cMessage.getSignMessage());
			BankLogUtils.printB2CVerifyResultLog(b2cMessage, verifyRes==0);
			return verifyRes == 0;
		} catch (Exception e) {
			BankLogUtils.printB2CVerifyExceptionLog(message, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6031);
		}
	}
	
	public String getPk(String pkFilePath) throws GopayException{
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC); 
		try {
			byte[] filePkByte = null;
			byte[] encPkByte = null;
			filePkByte = TransUtils.getFile(pkFilePath);
			encPkByte = ReturnValue.base64enc(filePkByte);
			return new String(encPkByte);
		} catch (FileNotFoundException e) {
			BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
		}		
	}

	public String getTranData(String plain) throws GopayException{
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC);
		try{
			byte[] bytes = ReturnValue.base64enc(plain.getBytes("UTF-8"));
			String tranData = new String(bytes);
			return tranData;
		}catch(Exception e){
			BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
		}
	}

	public PayB2CRes parse(IcbcB2cMessage message) throws GopayException{
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC);
		try{
			PayB2CRes res = new PayB2CRes();
			XStream xs = new XStream(new DomDriver());
			xs.autodetectAnnotations(true);
			xs.toXML(res);
			res = (PayB2CRes) xs.fromXML(message.getPlainMessage());
			return res;
		}catch(Exception e){
			BankLogUtils.printB2CVerifyExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6031);
		}
	}

}
